using System;
using System.Collections;
using System.Text;
using System.Xml;

namespace Slaks.DocumentSerialization.Document
{
	public class TermDocumentFrequencySerialization
	{
		public static void WriteXml(string path, IEnumerator termDocumentFrequencyEnumerator)
		{
			XmlTextWriter writer = null;

			try
			{
				writer = new XmlTextWriter(path, Encoding.UTF8);
				writer.Formatting = Formatting.Indented;

				writer.WriteStartDocument();

				writer.WriteStartElement(Grammar.TermDocumentFrequency.TermDocumentFrequencyElement);

				while (termDocumentFrequencyEnumerator.MoveNext())
				{
					TermDocumentFrequencyElement element = (TermDocumentFrequencyElement) termDocumentFrequencyEnumerator.Current;
					WriteTermDocumentFrequencyElement(writer, element);
				}

				writer.WriteEndElement();

				writer.WriteEndDocument();
			}
			catch (Exception ex)
			{
				throw ex;
			}
			finally
			{
				if (writer != null) writer.Close();
			}
		}

		private static void WriteTermDocumentFrequencyElement(XmlTextWriter writer, TermDocumentFrequencyElement element)
		{
			writer.WriteStartElement(Grammar.TermDocumentFrequency.EntryElement);
			writer.WriteElementString(Grammar.TermDocumentFrequency.TermIdElement, element.GetTermId().ToString());
			writer.WriteElementString(Grammar.TermDocumentFrequency.Frequency, element.GetDocumentCollection().Count.ToString());
			foreach (string documentName in element.GetDocumentCollection())
			{
				writer.WriteElementString(Grammar.TermDocumentFrequency.DocumentElement, documentName);
			}
			writer.WriteEndElement();
		}

		public static Id2DocumentFrequencyMap ReadXml(string path)
		{
			XmlTextReader reader = null;
			Id2DocumentFrequencyMap id2DocumentFrequencyMap = null;

			try
			{
				reader = new XmlTextReader(path);
				TermDocumentFrequencyElement element = null;
				id2DocumentFrequencyMap = new Id2DocumentFrequencyMap();
				while (reader.Read())
				{
					if (reader.NodeType != XmlNodeType.Element) continue;
					if (string.Equals(reader.Name, Grammar.TermDocumentFrequency.EntryElement))
					{
						element = ReadTermDocumentFrequencyElement(reader);
						if (element != null) id2DocumentFrequencyMap.Add(element.GetTermId(), element);
					}
				}
			}
			catch (Exception)
			{
				throw;
			}
			finally
			{
				if (reader != null) reader.Close();
			}

			return id2DocumentFrequencyMap;
		}

		private static TermDocumentFrequencyElement ReadTermDocumentFrequencyElement(XmlTextReader reader)
		{
			long id;
			long frequency = 0;
			long counter = 0;
			TermDocumentFrequencyElement element = null;
			while (reader.Read())
			{
				if (reader.NodeType != XmlNodeType.Element) continue;
				if (string.Equals(reader.Name, Grammar.TermDocumentFrequency.TermIdElement))
				{
					id = long.Parse(reader.ReadString());
					element = new TermDocumentFrequencyElement(id);
				}
				else if (string.Equals(reader.Name, Grammar.TermDocumentFrequency.Frequency))
				{
					frequency = long.Parse(reader.ReadString());
				}
				else if (string.Equals(reader.Name, Grammar.TermDocumentFrequency.DocumentElement))
				{
					element.AddDocument(reader.ReadString());
					counter++;
					if (counter >= frequency) break;
				}
			}

			if (frequency > counter) throw new Exception("Some error occurred while trying to parse document names in the entry with id " + element.GetTermId());
			return element;
		}

	}
}